/*****************************************************************************/
/**
 *  @file   MainView.cpp
 *  @author Naohisa Sakamoto
 */
/*----------------------------------------------------------------------------
 *
 *  Copyright (c) Visualization Laboratory, Kyoto University.
 *  All rights reserved.
 *  See http://www.viz.media.kyoto-u.ac.jp/kvs/copyright/ for details.
 *
 *  $Id: MainView.cpp 88 2013-12-27 14:49:59Z naohisa.sakamoto $
 */
/*****************************************************************************/
#include "MainView.h"
#include "OverView.h"
#include "DataSet.h"
#include "ResourceMonitor.h"
#include "Frustum.h"
#include "ResourceLabelWidget.h"
#include "OverViewUpdator.h"
#include <kvs/glut/Application>
#include <kvs/glut/Screen>
#include <kvs/RGBColor>
#include <kvs/ColorMap>
#include <kvs/TransferFunction>
#include <kvs/ObjectManager>
#include <kvs/RendererManager>
#include <kvs/ParticleBasedRenderer>
#include <kvs/StochasticUniformGridRenderer>
#include <kvs/StochasticRenderingCompositor>

#include <kvs/KeyPressEventListener>
class KeyPressEvent : public kvs::KeyPressEventListener
{
private:

    MainView* m_view;

public:

    KeyPressEvent( MainView* view )
    {
        m_view = view;
    }

    void update( kvs::KeyEvent* event )
    {
        switch ( event->key() )
        {
        case kvs::Key::o:
        {
            m_view->changeRenderer();
            break;
        }
        default: break;
        }
    }
};

MainView::MainView( kvs::glut::Application* app ):
    kvs::glut::Screen( app ),
    m_over_view( 0 ),
    m_data_set( 0 ),
    m_resource_monitor( 0 ),
    m_resource_label_widget( 0 ),
    m_over_view_updator( 0 )
{
    setTitle( "Main view" );
    setBackgroundColor( kvs::RGBColor::White() );

    m_compositor = new kvs::StochasticRenderingCompositor( this->scene() );
    m_compositor->setRepetitionLevel( 1 );
    m_compositor->enableLODControl();
    setEvent( m_compositor );
    addEvent( new KeyPressEvent( this ) );

    m_resource_label_widget = new ResourceLabelWidget( this ),
    m_resource_label_widget->show();
}

MainView::~MainView()
{
    if ( m_resource_label_widget ) delete m_resource_label_widget;
    if ( m_over_view_updator ) delete m_over_view_updator;
    if ( m_compositor ) delete m_compositor;
}

void MainView::attachOverViewScreen( OverView* over_view )
{
    m_over_view = over_view;
    m_over_view_updator = new OverViewUpdator( m_over_view );
    addEvent( m_over_view_updator );
}

void MainView::attachDataSet( DataSet* data_set )
{
    m_data_set = data_set;
    m_resource_label_widget->attachDataSet( data_set );
    m_over_view_updator->attachDataSet( m_data_set );
}

void MainView::attachResourceMonitor( ResourceMonitor* resource_monitor )
{
    m_resource_monitor = resource_monitor;
    m_resource_label_widget->attachResourceMonitor( resource_monitor );
}

void MainView::loadObject()
{
    if ( m_data_set->volume() )
    {
        size_t repeats = 1;

        if ( !m_data_set->particles() )
        {
            kvs::ColorMap cmap( 256 );
            cmap.addPoint( 0, kvs::RGBColor::Red() );
            cmap.addPoint( 255, kvs::RGBColor::Red() );
            cmap.create();

            kvs::TransferFunction tfunc( cmap );
            m_data_set->generateParticles( repeats, tfunc );
        }

        kvs::glsl::ParticleBasedRenderer* renderer = new kvs::glsl::ParticleBasedRenderer();
        renderer->setName( "OPBR" );
        renderer->setRepetitionLevel( repeats );

        scene()->registerObject( m_data_set->particles().get(), renderer );
    }
}

void MainView::changeRenderer()
{
    if ( scene()->rendererManager()->renderer("OPBR") )
    {
        typedef kvs::glsl::ParticleBasedRenderer OPBR;
        const OPBR* opbr = static_cast<OPBR*>( scene()->rendererManager()->renderer("OPBR") );
        m_initial_modelview = opbr->initialModelViewMatrix();
        m_initial_projection = opbr->initialProjectionMatrix();
        m_initial_viewport = opbr->initialViewport();

        kvs::ColorMap cmap( 256 );
        cmap.addPoint( 0, kvs::RGBColor::Red() );
        cmap.addPoint( 255, kvs::RGBColor::Red() );
        cmap.create();

        size_t repeats = 1;
        kvs::TransferFunction tfunc( cmap );
        kvs::StochasticUniformGridRenderer* renderer = new kvs::StochasticUniformGridRenderer();
        renderer->setName( "IPBR" );
        renderer->setRepetitionLevel( repeats );
        renderer->setTransferFunction( tfunc );

        scene()->replaceObject( 1, m_data_set->volume().get(), false );
        scene()->replaceRenderer( 1, renderer, true );
    }
    else
    {
        size_t repeats = 1;
        const kvs::Mat4& m = m_initial_modelview;
        const kvs::Mat4& p = m_initial_projection;
        const kvs::Vec4& v = m_initial_viewport;
        kvs::glsl::ParticleBasedRenderer* renderer = new kvs::glsl::ParticleBasedRenderer( m, p, v );
        renderer->setName( "OPBR" );
        renderer->setRepetitionLevel( repeats );

        scene()->replaceObject( 1, m_data_set->particles().get(), false );
        scene()->replaceRenderer( 1, renderer, true );
    }
}
